// `include    "top_define.v"

module lookup ( 
                      clk,
                      rst_n,

////   connect with  schedule

                      multi_mac_addr_en,
                      multi_mac_in,
                      multi_outport_en,
                      multi_group,




 //   connect with multi_hash
                     
                      multi_hash_en,
                      multi_hash_mac,
                      multi_mac,
                      multi_mac_hash_en,
                      hash_busy,

    //    connect with renew
             
                      rd_mac,
                      // wr_mac,
                      lookup_busy,
                      ini_multitable_busy,

//    connect wiht multi_addr_table
                       
                      wren_b,
                      addr_b,
                      q_b

                     );
                     
input clk;
input rst_n;

///    connect with schedule

input  multi_mac_addr_en;
input  [23:0]multi_mac_in;
output multi_outport_en;
output [7:0] multi_group;



//  connect with  multi_hash

input  multi_hash_en;
input  [9:0] multi_hash_mac;
output [23:0] multi_mac;
output multi_mac_hash_en;
input  hash_busy;

//  connect with    renew


output  [23:0]rd_mac;
// input [23:0]wr_mac;
output lookup_busy;
input ini_multitable_busy;
//    connect wiht multi_addr_table
                       
output wren_b;
output [9:0]addr_b;
input  [71:0]q_b;

//


reg    multi_outport_en;
reg    [7:0]multi_group;
reg    lookup_busy;

reg    [23:0] multi_mac;
reg    multi_mac_hash_en;

reg    [23:0]rd_mac;

reg    wren_b;
reg    [9:0]addr_b;



reg    lookup_done;

reg    [9:0]multi_hash_mac_reg;
reg    [23:0]multi_mac_reg;
reg    [2:0]step;
reg    [3:0] state;
reg    [3:0] next_state;

parameter  idle             = 4'b0001,
           hash_wait        = 4'b0010,
           hash             = 4'b0100,
           lookup           = 4'b1000;

   
           
always @ (posedge clk or negedge rst_n)
  if(~rst_n)
    state <=  idle;
  else
    state <=  next_state;
    

// always @ (state or multi_mac_addr_en or multi_hash_en or lookup_done or  hash_busy )
always@(*)
  case(state)
    idle:
      if(multi_mac_addr_en)
        next_state = hash_wait;
      else
        next_state = state;
    hash_wait:
      if(hash_busy | ini_multitable_busy)
        next_state = state;
      else
        next_state = hash; 
    hash:
      if(multi_hash_en)
        next_state = lookup;
      else
        next_state = state;
    lookup:
      if(lookup_done)
        next_state = idle;
      else
        next_state = state;

    default:
        next_state = idle;
  endcase


always @ (posedge clk or negedge rst_n)
  if(~rst_n)
    begin
      addr_b             <=  10'd0;
      wren_b             <=  1'b0;
      multi_mac_hash_en  <=  1'b0;
      multi_mac_reg      <=  24'd0;
      step               <=  3'd0;
      lookup_done        <=  1'b0;
      rd_mac             <=  24'b0;
      multi_mac          <=  24'b0;
      multi_hash_mac_reg <=  10'b0;
      lookup_busy        <=  1'b0;
      multi_outport_en   <= 1'b0;
      multi_group        <= 1'b0;
    end
  
  else
    begin
      case(state)
      idle:
        begin
        lookup_done        <=  1'b0; 
        step               <=  3'd0;
        if(multi_mac_addr_en)                           
        begin
        lookup_busy        <=  1'b1;
        rd_mac             <=  multi_mac_in;
        multi_mac_reg      <=  multi_mac_in;
        end
        end
        
      hash_wait:
        begin
        if(hash_busy | ini_multitable_busy)
        multi_mac_hash_en  <=  1'b0;
        else
        begin
        multi_mac          <=  multi_mac_reg;
        multi_mac_hash_en  <=  1'b1;
        end
        end
        
      hash:
        begin
        multi_mac_hash_en  <=  1'b0;
        if(multi_hash_en)
        multi_hash_mac_reg <=  multi_hash_mac;
        end  
        
        
      lookup:
        case(step)
        3'd0:
        begin
        wren_b             <=  1'b0;
        addr_b             <=  multi_hash_mac_reg;                 
        step               <=  3'd1;
        end
        3'd1:
        begin
        addr_b             <=  0;
        step               <=  3'd2;
        end
        3'd2:                                                            /// 1次查找
        begin
        if(q_b[64:41]      ==rd_mac && q_b[32]==1'b1)
        begin
        lookup_done        <=  1'b1; 
        multi_outport_en   <=  1'b1;
        multi_group        <=  q_b[40:33];
        step               <=  3'd6;
        end
        else
        begin
        multi_outport_en   <=  1'b1;
        multi_group        <=  8'b1111_1111;//广播
        step               <=  3'd6;
        lookup_done        <= 1'b1;
        end
        end
        3'd6:
        begin
        addr_b             <=  10'b0;
        multi_outport_en   <=  1'b0;
        multi_group        <=  8'd0;
        step               <=  3'd0;
        lookup_done        <=  1'b1; 
        multi_mac_reg      <=  24'd0;
        multi_mac          <=  24'b0;
        lookup_busy        <=  1'b0;
        multi_hash_mac_reg <=  8'b0;
        end
        default:
        begin
        multi_hash_mac_reg <=  8'b0;
        addr_b             <=  10'b0;
        multi_outport_en   <=  1'b0;
        multi_group        <=  8'd0;
        step               <=  3'd0;
        end
        endcase
        
     default:
        begin
        multi_group        <=  8'd0;
        multi_outport_en   <=  1'b0;
        addr_b             <=  10'd0; 
        wren_b             <=  1'b0;
        lookup_busy        <=  1'b0;
        step               <=  3'd0;
        end
        
        endcase
     end
 endmodule
